home *** CD-ROM | disk | FTP | other *** search
- /*
- CLUTLess
-
- In some instances it is desireable to store picts stripped of
- CLUTs in order to save some room in the disk. This sample shows
- how to create such picts and how to properly display them back.
-
- SimpleInC.c -- initialization stuff and event loop
- CLUTLess.c -- code that does the creation of the clut less pict;
- shows also how to display the pictures.
- CLUTLessFile.c --
- Routines to access files that have no direct
- relationship with picture handling.
-
- */
-
- /* In cases when there is a large number of picts containing eight bit pixmaps
- the color table associated to each one of them may add to a large ammount, in the
- cases when the color table for the different images is the same it is possible
- to save the disk space by storing the images with out cluts, storing one copy of
- the clut and then 'resotring the clut when displaying the image.
-
- This may be specially important for cd based apps that handle large number of images.
- Let assume for simplicity that each picture contains only one pixmap so the math
- goes like this, CLUT size = seed 4
- flags 2
- size 2
- ctTable 256*8 2048
- ---------------------
- 2K per pict
- So if the cd contains 1000 pictures the savings could be important.
-
- Note that there is the assumption here that the number of picts that can be rendered using
- the same clut is large, if this is not true then the overhead is not worth it.
-
- (The sample uses a picture to begin with but this is not important.)
- */
-
- #include "CLUTLess.h"
-
- /* The way we are going to handle this is the following:
-
- - Create PICT file containing striped pixmap and also the 'clut'
- - Read in the picture and its accompanying clut
-
- Note that for the purposes of this sample we use no spooling but this does not
- mean that it is not possible to use the techniques described here to create
- and display pictures along with file spooling.
- */
-
- /* proc returns true if the original picture has been read in, and a pict
- file was read in successfuly.
- */
- Boolean SetupPictures(void)
- {
- Boolean result = false;
-
- if ( SavePicture() ) { // Pict file was created.
- result = GetPictBack(); // and re-acqired
- }
- return result;
- }
-
-
- /* =============================================================================================== */
- /* =============================================================================================== */
- /*
- Here we create the picture and save it to disk
-
- */
- Boolean SavePicture(void)
- {
- GWorldPtr myGWorld;
- Rect gwRect;
- Boolean result = true; // return true in case user just wants to display a file
- CGrafPtr oldPort;
- GDHandle oldDevice;
- PicHandle localPict;
-
- GetGWorld(&oldPort, &oldDevice);
- // First we get the original pict from a resource.
- if ( !( gOrigPict = GetPicture(pictID) )) goto bail; // what use if no picture
- DetachResource((Handle)gOrigPict); // goes away when app quits
- gCurrPict = gOrigPict;
-
- gwRect = (*gOrigPict)-> picFrame;
-
- if ( NewGWorld(&myGWorld, desiredDepth, &gwRect, nil, nil, 0) ) goto bail; // no offscreen
- if (LockPixels(GetGWorldPixMap(myGWorld))) {
-
- SetGWorld(myGWorld, nil); // draw the image offscreen
- DrawPicture(gOrigPict, &gwRect);
- SetGWorld(oldPort, oldDevice);
- if ( localPict = CreateCLUTLessPict(myGWorld) ) {
- if ( SaveCLUTLessPict(localPict) ) {
- result = true;
- }
- }
- UnlockPixels(GetGWorldPixMap(myGWorld));
- DisposeGWorld(myGWorld);
- }
- bail:
- return result;
- }
-
- /* =============================================================================================== */
- /*
- the process we want to exemplify when creating the picture is the following:
-
- 1- Create a GWorld and 'display' the image there.
- 2- Call OpenPicture to start recording
- 3- Set the color table handle in the source pixmap to nil
- 4- Call CopyBits to store the image sans clut in the picture
- 5- Call ClosePicture to complete the process
-
- */
- PicHandle CreateCLUTLessPict(GWorldPtr myGWorld) { // at this point clut is already locked
-
- PicHandle new = nil;
- PixMapHandle pm;
- BitMap *srcPix;
- Rect offRect = myGWorld->portRect;
- CGrafPtr oldPort;
- GDHandle oldDevice;
-
- GetGWorld(&oldPort, &oldDevice);
-
- pm = GetGWorldPixMap(myGWorld);
- HLock((Handle)pm);
- srcPix = (BitMap *) *pm; // get pointer to make code more readable
- gSharedClut = (*pm)->pmTable;
- (*pm)->pmTable = nil; // set pixmap clut to nil
-
- SetGWorld(myGWorld, nil);
- ClipRect(&offRect);
- new = OpenPicture(&offRect); // gWorld rect was created from pict rect
- CopyBits(srcPix, // when creating a pict source is what really matters
- srcPix, // use same as dest
- &offRect, // nice rect
- &offRect, // same
- srcCopy,
- nil);
- ClosePicture(); // completes creation process
-
- HUnlock((Handle)pm);
- (*pm)->pmTable = gSharedClut; // put this back
-
- HandToHand((Handle *)(&gSharedClut)); // make a copy of the clut so it can be stored in the file
- // handle gets disposed when closing resource file.
- SetGWorld(oldPort, oldDevice);
- return new;
- }
-
- /* =============================================================================================== */
- /* Given that this picts are not going to look well without some
- pre-processing the best way to store them is not a PICT file that users
- may feel tempted to view with some other app.If the picts are not very big
- in size then resources could be used, for large images a data file is recommended.
-
- For the exercise we'll use a pict file that is easy to disect; the following
- code promts the user for a place where to put the resulting pict and the
- 'clut' resource to be used when viewing it.
-
-
- */
- Boolean SaveCLUTLessPict(PicHandle aPict) {
- Point dlgPos = {100,100}; /* Position the dialog box */
- SFReply sfr; /* StdFile reply */
- short fileRef;
- long pictSize = GetHandleSize((Handle)aPict);
- Boolean result = false;
-
- /* Prompt the user for a file name and create it */
- SFPutFile(dlgPos, "\pPICT file to create:","\pPICT File",nil,&sfr);
- if (sfr.good) {
- if ( fileRef = OpenPictureFile(&sfr) ) {
- HLock((Handle)aPict);
- if ( FSWrite(fileRef, &pictSize, (Ptr)*aPict) )
- KillFile(fileRef, &sfr);
- else {
- ClosePictureFile(fileRef, &sfr, aPict);
- result = true;
- }
- HUnlock((Handle)aPict);
- }
- }
- /* the pict is in the file now we save the 'clut' resource that will allow
- to view the image in its full color.
- */
- SaveCLUTResource(&sfr);
-
- return result;
- }
-
- /* =============================================================================================== */
- /* =============================================================================================== */
- /* this is the replacement for the standard bits proc. When a picture is being drawn]
- the routine is called just before the pixmap is transferred to the destination;
- at this time our routine will replace the color table filed with the color
- table contained in the 'clut' resource.
- */
-
- pascal void AddClutProc(BitMap *src,
- Rect *srcR, Rect *dstR,
- short mode, RgnHandle msk)
- {
- CTabHandle saveCTH;
-
- // Save color table handle.
- saveCTH = ((PixMapPtr) src)->pmTable;
- // Put 'clut' resource.
- ((PixMapPtr) src)->pmTable = gSharedClut;
- // Let QuickDraw do the work.
- StdBits(src, srcR, dstR, mode, msk);
- // Restore saved handle and return.
- ((PixMapPtr) src)->pmTable = saveCTH;
- }
-
- void InitProcs(CQDProcs *theProcs)
- {
- SetStdCProcs(theProcs); // default procs
- theProcs->bitsProc = NewQDBitsProc(AddClutProc);
- }
-
-
-